# coding: utf-8
import cv2
import numpy as np
from typing import Tuple

np.set_printoptions(threshold=1e6)


class SplitQrCode(object):

    def __init__(self):
        pass

    # def __check_file_path(self, filePath: str):
    #     assert os.path.exists(filePath), FileExistsError(f"The input file path: [{filePath}] is not exist, Please check it!")

    def __imread(self, imagePath: str):
        # self.__check_file_path(imagePath)
        try:
            image = cv2.imread(imagePath, 0)
            return image
        except Exception as e:
            raise IOError(f"Read image file: [{imagePath}] error! Make sure it`s an image file.")

    def __get_kernel(self, size):
        return np.ones((size, size), np.uint8)

    def __get_main_pixel(self, image: np.ndarray):
        """
        获取最多和第二多的像素，最多的是背景黑色
        :param image:
        :return: 返回最多和第二多的像素值
        """
        # 像素直方图
        # 一、images（输入图像）参数必须用方括号括起来。
        # 二、计算直方图的通道。
        # 三、Mask（掩膜），一般用None，表示处理整幅图像。
        # 四、histSize，表示这个直方图分成多少份（即多少个直方柱）。
        # 五、range，直方图中各个像素的值，[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。
        hist = cv2.calcHist([image], [0], None, [256], [0, 256])
        #
        max_index = np.argmax(hist)
        hist[max_index] = np.min(hist)
        second_index = np.argmax(hist)
        return max_index, second_index

    def __crop_image(self, image, size: Tuple[int, int] = (3, 3), *args):
        """
        切割图片
        :param image:
        :param size: 图片切割比例，这里是3*3,
        :param args: 备用
        :return: 返回切割后的图片像素值以及对应坐标
        """
        img = image.copy()
        height, width = img.shape
        cell_width = width // size[0]
        cell_height = height // size[1]
        for h in range(size[0]):
            for w in range(size[1]):
                cropped = img[h * cell_height:(h + 1) * cell_height, w * cell_width: (w + 1) * cell_width]
                yield cropped, (h, w)

    def run(self, filePath: str):
        # Read image  灰度化
        image = self.__imread(filePath)

        # Find the maximum and the second pixel in image map.
        # And then repleace them with 0(black).
        max_pixel, second_pixel = self.__get_main_pixel(image)
        # 将灰度化的图片对应的rgb像素转化为黑色
        image[image == max_pixel] = 0
        image[image == second_pixel] = 0
        # self.__show(image)
        cv2.imwrite(f"image/10.png", image)
        # Devide the image into 9, and return them into the ocr detector.膨胀幅度
        kernel3 = self.__get_kernel(3)
        kernel5 = self.__get_kernel(5)
        kernel7 = self.__get_kernel(7)
        kernel9 = self.__get_kernel(9)
        devided_image = self.__crop_image(image, size=(3, 3))
        coun = 1
        data = []
        for cropped_img, coordniate in devided_image:
            # self.__show(cropped_img)
            cropped_img = cv2.morphologyEx(cropped_img, cv2.MORPH_TOPHAT, kernel5)
            crop_max_pixel, crop_second_pixel = self.__get_main_pixel(cropped_img)
            self.__show(cropped_img)
            cropped_img[cropped_img != crop_second_pixel] = 0
            # self.__show(cropped_img)
            cropped_img[cropped_img != 0] = 255
            # self.__show(cropped_img)
            cropped_img = cv2.dilate(cropped_img, kernel5, iterations=1)
            cropped_img = cv2.erode(cropped_img, kernel3, iterations=1)
            self.__show(cropped_img)
            print(coordniate)
            cv2.imwrite(f"image/{coun}.png", cropped_img)
            coun += 1
            # 百度识别
            client = AipOcr('23325703', 'Mi3wTN1BcGSkMGmPYjUvFGG0', 'C9psnohQTyzxk0sUiocaypmsZYcL7woZ')
            we = open(f"image/{coun - 1}.png", 'rb')
            img = we.read()
            message = client.basicAccurate(img)
            print(f'{message}')
            try:
                data.append(message['words_result'][0]['words'])
            except:
                data.append('')
            time.sleep(1)
        return data

    def __show(self, image, name="image"):
        cv2.imshow(name, image)
        cv2.waitKey(0)


if __name__ == '__main__':
    cc = SplitQrCode()
    cc.run('1.png')
